package com.legendshop.openportal.sdk.validator;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.legendshop.openportal.sdk.annotation.JsonValid;
import com.legendshop.openportal.sdk.exception.OpenClientException;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.HibernateValidator;

import javax.validation.*;
import java.util.List;
import java.util.Set;

/**
 * @author jzh
 * @version 1.0.0
 * @title JsonValidator
 * @date 2024/6/29 9:21
 * @description：json格式校验
 */
@Slf4j
public class JsonValidator implements ConstraintValidator<JsonValid, Object> {

    /**
     * 枚举注解
     */
    private JsonValid annotation;
    private static final Validator validator;

    static {
        ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
                .configure()
                .addProperty("hibernate.validator.fail_fast", "true")
                .buildValidatorFactory();
        validator = validatorFactory.getValidator();
    }

    @Override
    public void initialize(JsonValid constraintAnnotation) {
        this.annotation = constraintAnnotation;
    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {

        Class<?> targetClass = annotation.target();
        boolean ignoreEmpty = annotation.ignoreEmpty();
        if (ignoreEmpty && ObjectUtil.isEmpty(value)) {
            return Boolean.TRUE;
        } else if (!ignoreEmpty && ObjectUtil.isEmpty(value)) {
            log.info("参数为空");
            return Boolean.FALSE;
        }

        int maxSize = annotation.arrayMaxSize();
        String json = StrUtil.toString(value);

        // json数组校验
        if (annotation.isArrayJson()) {
            if (!JSONUtil.isJsonArray(json)) {
                log.info("参数不是json数组");
                return Boolean.FALSE;
            }
            List<?> list = null;
            try{
                list = JSONUtil.parseArray(json).toList(targetClass);
                if (maxSize > 0 && list.size() > maxSize) {
                    log.info("json数组过长");
                    return Boolean.FALSE;
                }
            }catch (Exception e){
                log.warn("JSON格式错误, json = {}", json);
                return Boolean.FALSE;
            }


            if (!ignoreEmpty && CollUtil.isEmpty(list)) {
                log.info("json数组为空");
                return Boolean.FALSE;
            }

            for (Object object : list) {
                Set<ConstraintViolation<Object>> validate = validator.validate(object);
                if (CollUtil.isNotEmpty(validate)) {
                    log.info("json字段校验不通过，error: {}", validate.stream().map(ConstraintViolation::getMessage).findFirst().orElse(null));
                    return Boolean.FALSE;
                }
            }
        } else {
            // json对象校验
            if (!JSONUtil.isJsonObj(json)) {
                log.info("参数不是json对象");
                return Boolean.FALSE;
            }
            Object object = null;
            try{
                object = JSONUtil.toBean(json, targetClass);
            }catch (Exception e){
                log.info("json格式有误, json = {}", json);
                return Boolean.FALSE;
            }

            if (!ignoreEmpty && ObjectUtil.isEmpty(object)) {
                log.info("json为空");
                return Boolean.FALSE;
            }

            Set<ConstraintViolation<Object>> validate = validator.validate(object);
            if (CollUtil.isNotEmpty(validate)) {
                String msg = validate.stream().map(ConstraintViolation::getMessage).findFirst().orElse(null);
                log.info("json字段校验不通过，error: {}", msg);
                throw new OpenClientException(msg);
            }
        }

        return true;
    }


}
